package com.idea.relax.redis.lock.client;


import com.idea.relax.redis.lock.support.LockType;
import com.idea.relax.redis.lock.support.CheckedSupplier;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public interface RedisLockClient {

    /**
     * 尝试获取锁
     * @param lockName
     * @param lockType
     * @param waitTime
     * @param leaseTime
     * @param timeUnit
     * @return
     * @throws InterruptedException
     */
    boolean tryLock(String lockName, LockType lockType, long waitTime,
                    long leaseTime, TimeUnit timeUnit) throws InterruptedException;

    /**
     * 释放锁
     * @param lockName
     * @param lockType
     */
    void unLock(String lockName, LockType lockType);

    /**
     * 加锁
     * @param lockName
     * @param lockType
     * @param waitTime
     * @param leaseTime
     * @param timeUnit
     * @param target
     * @param <T>
     * @return
     */
    <T> T lock(String lockName, LockType lockType, long waitTime,
               long leaseTime, TimeUnit timeUnit, CheckedSupplier<T> target);

    /**
     * 公平锁
     * @param lockName
     * @param waitTime
     * @param leaseTime
     * @param target
     * @param <T>
     * @return
     */
    default <T> T lockFair(String lockName, long waitTime, long leaseTime, CheckedSupplier<T> target) {
        return this.lock(lockName, LockType.FAIR, waitTime, leaseTime, TimeUnit.SECONDS, target);
    }

    /**
     * 可重入锁
     * @param lockName
     * @param waitTime
     * @param leaseTime
     * @param target
     * @param <T>
     * @return
     */
    default <T> T lockReentrant(String lockName, long waitTime, long leaseTime, CheckedSupplier<T> target) {
        return this.lock(lockName, LockType.REENTRANT, waitTime, leaseTime, TimeUnit.SECONDS, target);
    }

}
